#include "ZAllRoot.h"
#include "ZBox.h"
#include "ZImage.h"
#include "ZText.h"
#include "ZMap.h"
#include "ZWalker.h"

namespace Zdib
{
	CAllRoot::CAllRoot(HDC hdc):CContainer(NULL)
	{
		TColor color;
		color.a=255;
		color.b=255;
		color.g=255;
		color.r=255;
		this->m_Img=new CImgFile();
		m_Img->SetSize(ScreenW,ScreenH);
		m_Img->SetMake(false);
//		m_BgImg=new CImgFile();
//		m_BgImg->LoadFile("E:\\myproject\\Zdib\\debug\\bg.bmp");
//		m_BgImg->SetMake(false);
		m_hDc=hdc;
		//m_BghDc=CreateCompatibleDC(0);
		m_ImgForFile.setlength(100);
		m_MapForFile.setlength(20);
		W=ScreenW;
		H=ScreenH;
		//m_hbmp=CreateDIBitmap(hdc,m_Img->headInfo,0,m_Img->PixColors,(BITMAPINFO*)m_Img->headInfo,0);
		//m_hbmp=CreateDIBSection(hdc,(BITMAPINFO*)m_Img->headInfo,DIB_RGB_COLORS,(void**)&m_BgData,NULL,0);
		//free(m_Img->PixColors);
		//m_Img->PixColors=(PColor)m_BgData;
		//SelectObject(m_BghDc,m_hbmp);
		NowFocus=NULL;
		m_AllCallBack=new TZList(100);
	}

	CAllRoot::~CAllRoot()
	{
		PTimeCallBack tempcb;
		delete m_Img;
//		delete m_BgImg;
		int i;
		CImgFile *temp;
		for(i=m_ImgForFile.count-1;i>=0;i--)
		{
			temp=(CImgFile *)m_ImgForFile.items(i);
			m_ImgForFile.del(i);
			delete temp;
		}
		CMapFile *temp1;
		for(i=m_MapForFile.count-1;i>=0;i--)
		{
			temp1=(CMapFile *)m_MapForFile.items(i);
			m_MapForFile.del(i);
			delete temp1;
		}
		for(i=m_AllCallBack->count-1;i>=0;i--)
		{
			tempcb=(PTimeCallBack)m_AllCallBack->items(i);
			if(tempcb->IsOver)
			{
				delete tempcb;
			}
			else
				tempcb->IsOver=true;
		}
		delete m_AllCallBack;
	}

	CImgFile *CAllRoot::GetCurImg()
	{
		return m_Img;
	}

	CSpiritImgFile *CAllRoot::GetImgForPath(char *filename)
	{
		CSpiritImgFile *tempfile;
		int i;
		for(i=0;i<m_ImgForFile.count;i++)
		{
			tempfile=(CSpiritImgFile *)m_ImgForFile.items(i);
			if(strlen(filename)!=strlen(tempfile->FileName))
				continue;
			if(memcmp(filename,tempfile->FileName,strlen(filename))==0)
			{
				return tempfile;
			}
		}
		tempfile=new CSpiritImgFile();
		tempfile->LoadFile(filename);
		m_ImgForFile.add((LPVOID)tempfile);
		return tempfile;
	}

	CMapFile *CAllRoot::GetMapForPath(char *filename)
	{
		CMapFile *tempfile;
		int i;
		for(i=0;i<m_MapForFile.count;i++)
		{
			tempfile=(CMapFile *)m_MapForFile.items(i);
			if(strlen(filename)!=strlen(tempfile->FileName))
				continue;
			if(memcmp(filename,tempfile->FileName,strlen(filename))==0)
			{
				return tempfile;
			}
		}
		tempfile=new CMapFile();
		tempfile->LoadFile(filename);
		m_MapForFile.add((LPVOID)tempfile);
		return tempfile;
	}

	CContainer *CAllRoot::CreateBase(CContainer *parent)
	{
		CContainer *base;
		if(parent==NULL)
		{
			base=new CContainer((CContainer *)this);
		}
		else
		{
			base=new CContainer(parent);
		}
		base->SetRoot((CContainer*)this);
		return base;
	}

	CBox *CAllRoot::CreateBox(CContainer *parent,int w,int h,TColor color,BYTE alpha)
	{
		CBox *box;
		if(parent==NULL)
			box=new Zdib::CBox((CContainer *)this,(CContainer *)this,w,h,color,alpha);
		else
			box=new Zdib::CBox((CContainer *)this,parent,w,h,color,alpha);
		return box;
	}

	CImager *CAllRoot::CreateImager(CContainer *parent,char *filepack)
	{
		CImager *img;
		if(parent==NULL)
			img=new Zdib::CImager((CContainer *)this,(CContainer *)this,filepack);
		else
			img=new Zdib::CImager((CContainer *)this,parent,filepack);
		return img;
	}

	CCutImager *CAllRoot::CreateCutImager(CContainer *parent,char *filepack)
	{
		CCutImager *img;
		if(parent==NULL)
			img=new Zdib::CCutImager((CContainer *)this,(CContainer *)this,filepack);
		else
			img=new Zdib::CCutImager((CContainer *)this,parent,filepack);
		return img;
	}

	CWalker *CAllRoot::CreateWalker(CContainer *parent,char *filepack)
	{
		CWalker *walker;
		if(parent==NULL)
		{
			walker=new Zdib::CWalker((CContainer *)this,(CContainer *)this,filepack);
		}
		else
		{
			walker=new Zdib::CWalker((CContainer *)this,parent,filepack);
		}
		return walker;
	}

	CHero *CAllRoot::CreateHero(CContainer *parent,char *filepack)
	{
		CHero *hero;
		if(parent==NULL)
		{
			hero=new Zdib::CHero((CContainer *)this,(CContainer *)this,filepack);
		}
		else
		{
			hero=new Zdib::CHero((CContainer *)this,parent,filepack);
		}
		return hero;
	}

	CText *CAllRoot::CreateText(CContainer *parent,char *txt,HFONT font,TColor color)
	{
		CText *text;
		if(parent==NULL)
			text=new Zdib::CText((CContainer *)this,(CContainer *)this,txt,font,color);
		else
			text=new Zdib::CText((CContainer *)this,parent,txt,font,color);
		return text;
	}

	CRichText *CAllRoot::CreateRichText(CContainer *parent,char *txt,int w,HFONT font,TColor color)
	{
		CRichText *text;
		if(parent==NULL)
			text=new Zdib::CRichText((CContainer *)this,(CContainer *)this,txt,w,font,color);
		else
			text=new Zdib::CRichText((CContainer *)this,parent,txt,w,font,color);
		return text;
	}

	CMap *CAllRoot::CreateMap(CContainer *parent,char *filename)
	{
		CMap *map;
		if(parent==NULL)
			map=new Zdib::CMap((CContainer *)this,(CContainer *)this,filename);
		else
			map=new Zdib::CMap((CContainer *)this,(CContainer *)parent,filename);
		return map;
	}
	
	PTimeCallBack CAllRoot::SetCallBack(LPVOID po,LPVOID (*CallBack)(LPVOID lp,LPVOID argv[]),unsigned short int frame,LPVOID argv[])
	{
		PTimeCallBack tempcb;
		tempcb=new TTimeCallBack;
		tempcb->CallBack=CallBack;
		tempcb->Argv=argv;
		tempcb->MaxFrame=frame;
		tempcb->CurFrame=frame;
		tempcb->IsOver=false;
		tempcb->PObj=po;
		m_AllCallBack->add((LPVOID)tempcb);
		return tempcb;
	}
	
	void CAllRoot::LoopFun()
	{
		int i;
		LPVOID lp=NULL;
		PTimeCallBack tempcb;
		CContainer *obj;
		for(i=m_AllCallBack->count-1;i>=0;i--)
		{
			lp=NULL;
			tempcb=(PTimeCallBack)m_AllCallBack->items(i);
			if(tempcb->IsOver)
			{
				delete tempcb;
				m_AllCallBack->del(i);
				continue;
			}
			if(tempcb->CurFrame==0 && tempcb->CallBack!=NULL)
			{
				lp=tempcb->CallBack(tempcb->PObj,tempcb->Argv);
				if(lp==NULL)
				{
					obj=(CContainer *)tempcb->PObj;
					obj->FreeCallBack(tempcb);
					continue;
				}
				tempcb->CurFrame=tempcb->MaxFrame;
			}
			else
			{
				tempcb->CurFrame-=1;
			}
		}
	}

	void CAllRoot::Draw()
	{
		LoopFun();
		//m_Img->Draw(m_BgImg,0,0,false);
//		MoveMemory((char *)m_Img->PixColors,(char *)m_BgImg->PixColors,m_Img->headInfo->biSizeImage);
		CContainer::Draw();
		//MoveMemory((char *)m_BgData,(char *)m_Img->PixColors,m_Img->headInfo->biSizeImage);
		StretchDIBits(m_hDc,0,0,W,H,0,0,W,H,(LPVOID)m_Img->PixColors,(BITMAPINFO *)m_Img->headInfo,DIB_RGB_COLORS,SRCCOPY);
		//BitBlt(m_hDc,0,0,W,H,m_BghDc,0,0,SRCCOPY);
		//SetDIBitsToDevice(m_hDc,0, 0, W, H, 0, 0, 0, H, (LPVOID)m_Img->PixColors, (BITMAPINFO *)m_Img->headInfo, DIB_RGB_COLORS);
	}
	
	CContainer *CAllRoot::FindObjFor(int x,int y)
	{
		return GetObjForPoint(x,y);
	}

	void CAllRoot::SetOnFocus(CContainer *now)
	{
		if(NowFocus)
		{
			Zdib::TEvent newEvent;
			newEvent.event_type=ET_MouseEvent;
			newEvent.Mouse.Call=NowFocus;
			newEvent.Mouse.CallBack=NULL;
			newEvent.Mouse.mouse_type=ME_MouseLeave;
			newEvent.Mouse.wheel=0;
			newEvent.Mouse.x=0;
			newEvent.Mouse.y=0;
			NowFocus->SetIsNowFocus(false);
			NowFocus->OnEvent(newEvent);
		}
		if(now)
		{
			Zdib::TEvent enter;
			enter.event_type=ET_MouseEvent;
			enter.Mouse.Call=now;
			enter.Mouse.CallBack=NULL;
			enter.Mouse.mouse_type=ME_MouseEnter;
			enter.Mouse.wheel=0;
			enter.Mouse.x=0;
			enter.Mouse.y=0;
			now->SetIsNowFocus(true);
			now->OnEvent(enter);	
		}
		NowFocus=now;
	}

	void CAllRoot::ProcEvent(const TEvent& ev)
	{
		switch(ev.event_type)
		{
		case ET_MouseEvent:
			CContainer *actobj;
			actobj=FindObjFor(ev.Mouse.x,ev.Mouse.y);
			if(!actobj)
			{
				SetOnFocus(NULL);
				break;
			}
			if(actobj!=NowFocus)
			{
				SetOnFocus(actobj);
				break;
			}
			if(actobj)
			{
				m_Tempev.event_type=ev.event_type;
				m_Tempev.Mouse.Call=actobj;
				m_Tempev.Mouse.CallBack=NULL;
				m_Tempev.Mouse.mouse_type=ev.Mouse.mouse_type;
				m_Tempev.Mouse.wheel=ev.Mouse.wheel;
				m_Tempev.Mouse.x=ev.Mouse.x;
				m_Tempev.Mouse.y=ev.Mouse.y;
				actobj->OnEvent(m_Tempev);
			}
			break;
		case ET_KeyEvent:
			break;
		default:
			break;
		}
	}

}